clear;clc;

%% Setup
% Information Structure
TargetParamInfo =   struct('b_lb',struct('lb',-0.4,'ub',-0.20,'v0',-0.25),...
                           'B_Total_SS',struct('lb',0.80,'ub',0.95,'v0',0.9),...
                           'O_AdjCostVec_FI',struct('lb',0.1*ones(2,1),'ub',7*ones(2,1),'v0',ones(2,1)), ...
                           'O_AdjCostVec_RI',struct('lb',0.1*ones(2,1),'ub',7*ones(2,1),'v0',ones(2,1)) ...
                           );
Info            =   struct('TargetParam',TargetParamInfo);
Info.InputParam =   struct('KAPPA',0.00/4,'XI',1/82.5/4,'Pir_SS',0.02/4,...
                            'TrProb_ext',0.92,'Prob_ext',0.33,...
                            'TrProb_H',0.96,'Prob_H',0.37,...'b_lb',-0.29,'B_Total_SS',0.90,...
                            'Fin_DomShare',0.79,'Fin_AdjCost',1,...
                            'Cons_FracT',0.5,'Cons_FracH',0.6);
% Info.InputParam =   struct('KAPPA',0.00/4,'XI',1/82.5/4,'Pir_SS',0.02/4,...
%                             'TrProb_ext',0.90,'Prob_ext',0.33,...
%                             'TrProb_H',0.90,'Prob_H',0.37,...'b_lb',-0.29,'B_Total_SS',0.90,...
%                             'Fin_DomShare',0.79,'Fin_AdjCost',1,...
%                             'Cons_FracT',0.5,'Cons_FracH',0.6);
                        
Info.StatName   =   {'Wealth-Income Ratio: Median',...'Median Wealth/Median Income','Prob. of Negative Wealth',...
                     'MPC: Median', ...,'Prob. of HtM','MPC: Average' ...
                     'Gap in TrProbMat' ...'Different between the endogenous average transition prob and exogenous tr. prob.'
                     };
Info.Stat_Data  =   [0.35;0.15;zeros(4,1)];
Info.Stat_Weight=   [1;1;ones(4,1)*100];

Info.ParamList  =   {'b_lb','B_Total_SS','O_AdjCostVec_FI','O_AdjCostVec_RI'}; %
ParamVec_0      =   [];
lb              =   [];
ub              =   [];
Idx_0           =   0;
for ii=1:length(Info.ParamList)
    pp              =   Info.ParamList{ii};
    ParamVec_0      =   [ParamVec_0;Info.TargetParam.(pp).v0];
    lb              =   [lb;Info.TargetParam.(pp).lb];
    ub              =   [ub;Info.TargetParam.(pp).ub];
    TempDim         =   length(Info.TargetParam.(pp).v0);
    Info.Idx.(pp)   =   Idx_0+(1:TempDim)';
    Idx_0           =   Idx_0+TempDim;
end
% Optimization 
ObjFunction     =   @(Input)Study_2_Calibration_Eval(Info,Input);

%% Global Optimization
warning('off','all');

%--------------------------------------------------------------------------
% Particle Swarm
%--------------------------------------------------------------------------
rng default
options             =   optimoptions('particleswarm',...
                                     'Display','iter',...'SwarmSize',100.'HybridFcn',@fmincon,..
                                     'MaxTime',60*60*2,'UseParallel',true);
[ParamVec,fval,exitflag] ...
                    =   particleswarm(ObjFunction,length(lb),lb,ub,options);

[~,Result]          =   ObjFunction(ParamVec);

save('Result_2_Calibration.mat','Info','Result','ParamVec');
% save('Result_2_Calibration_LowPers.mat','Info','Result','ParamVec');